package com.erf.message;

import com.erf.tools.ByteUtil;
import com.erf.tools.SequenceUtil;
import io.netty.buffer.ByteBuf;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;

import java.nio.charset.StandardCharsets;

/**
 * @author zhangzy
 * @date 2022/7/5
 */
@AllArgsConstructor
@NoArgsConstructor
@Data
@EqualsAndHashCode(callSuper = false)
@Slf4j
public class SubmitRequest extends BaseMessage {
    private int classNameLength;
    private String className;
    private int springInvokeNameLength;
    private String springInvokeName;
    private int methodNameLength;
    private String methodName;

    private int paramsTypesLength;
    private Class<?>[] paramsTypes;
    private int paramsValuesLength;
    private Object[] paramsValues;

    @Override
    public void encode(ByteBuf byteBuf) {
        byte[] classNameBytes = className.getBytes(StandardCharsets.UTF_8);
        classNameLength = classNameBytes.length;
        byte[] springInvokeNameBytes = springInvokeName.getBytes(StandardCharsets.UTF_8);
        springInvokeNameLength = springInvokeNameBytes.length;
        byte[] methodNameBytes = methodName.getBytes(StandardCharsets.UTF_8);
        methodNameLength = methodNameBytes.length;
        byte[] typeBytes = ByteUtil.encodeObjectToBytes(paramsTypes);
        paramsTypesLength = typeBytes.length;
        byte[] bytes = ByteUtil.encodeObjectToBytes(paramsValues);
        paramsValuesLength = bytes.length;
        //赋值
        int messageLength = 12 + 4 + classNameLength + 4 + springInvokeNameLength + 4 + methodNameLength + 4 + paramsTypesLength + 4 + paramsValuesLength;
        byteBuf.writeInt(messageLength);
        byteBuf.writeInt(0x00000002);
        byteBuf.writeInt(this.getSequence());

        byteBuf.writeInt(classNameLength);
        byteBuf.writeBytes(classNameBytes);
        byteBuf.writeInt(springInvokeNameLength);
        byteBuf.writeBytes(springInvokeNameBytes);
        byteBuf.writeInt(methodNameLength);
        byteBuf.writeBytes(methodNameBytes);
        byteBuf.writeInt(paramsTypesLength);
        byteBuf.writeBytes(typeBytes);
        byteBuf.writeInt(paramsValuesLength);
        byteBuf.writeBytes(bytes);

    }

    @Override
    public BaseMessage decode(int length, int command, int sequence, ByteBuf body) {
        this.setLength(length);
        this.setCommand(command);
        this.setSequence(sequence);
        classNameLength = body.readInt();
        className = body.readCharSequence(classNameLength, StandardCharsets.UTF_8).toString();
        springInvokeNameLength = body.readInt();
        springInvokeName = body.readCharSequence(springInvokeNameLength, StandardCharsets.UTF_8).toString();
        methodNameLength = body.readInt();
        methodName = body.readCharSequence(methodNameLength, StandardCharsets.UTF_8).toString();

        paramsTypesLength = body.readInt();
        byte[] typeBytes = new byte[paramsTypesLength];
        body.readBytes(typeBytes);
        Object ot = ByteUtil.decodeBytesToObject(typeBytes);
        paramsTypes = (Class<?>[]) ot;

        paramsValuesLength = body.readInt();
        byte[] paramsBytes = new byte[paramsValuesLength];
        body.readBytes(paramsBytes);
        Object o = ByteUtil.decodeBytesToObject(paramsBytes);
        paramsValues = (Object[]) o;
        return this;
    }
}
